package com.hbx.platform.base.service.impl;

import com.hbx.platform.auth.domain.Permission;
import com.hbx.platform.auth.service.impl.PermissionServiceImpl;
import com.hbx.platform.base.annotation.AutoPermission;
import com.hbx.platform.base.service.IAutoPermissionService;
import com.hbx.platform.base.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author: hbx
 * @date: 2024/04/07
 **/
@Service
public class AutoPermissionServiceImpl implements IAutoPermissionService {

    @Autowired
    private PermissionServiceImpl permissionService;

    @Value("${autoInit.paths}")
    private String paths;
    @Value("${autoInit.tages}")
    private Boolean tages;

    /**
     * 通过反射得到@AutoPermission标识的类和方法
     * 将类信息和方法信息按照数据库中表的格式存储为权限
     */
    @Override
    public void AutoInit() {
        //读取application.yml的tages配置来决定是否扫描AutoPermission标识的类和方法，去更新权限
        if(!tages) return; //控制开关
        //获取一个包下面的所有类全限定名
        List<Class> controllers = ClassUtils.getAllClassName(paths);
        for (Class controller : controllers) {//过滤、筛选
            AutoPermission autoPermission = (AutoPermission) controller.getAnnotation(AutoPermission.class);
            //判断当前类是否标注AutoPermission注解
            //为空就跳过，不在权限控制范围内
            if(autoPermission == null) continue;
            //创建父权限对象，作填充
            Permission parent = new Permission();
            //类名
            parent.setName(autoPermission.name());
            //类描述
            parent.setDescs(autoPermission.desc());
            //类名
            parent.setSn(controller.getSimpleName());
            //@RequestMapping注解可以配合多个访问路径
            RequestMapping requestMapping = (RequestMapping) controller.getAnnotation(RequestMapping.class);
            parent.setUrl(requestMapping.value()[0]);//获取注解RequestMapping上的路径

            //检查db里面是否存在当前权限
            Permission permissionParent = permissionService.queryBySn(parent.getSn());
            if(permissionParent == null){
                permissionService.save(parent);
            }else{
                parent.setId(permissionParent.getId());
                permissionService.update(parent);
            }
            //获取当前控制层的方法
            Method[] methods = controller.getMethods();
            for (Method method : methods) {
                //获取自定义注解标识了的方法
                AutoPermission autoPermissionMethod = method.getAnnotation(AutoPermission.class);
                //没标识，跳过
                if(autoPermissionMethod == null) continue;
                //创建子权限
                Permission children = new Permission();
                children.setName(autoPermissionMethod.name());
                children.setDescs(autoPermissionMethod.desc());
                //类名+方法
                children.setSn(parent.getSn() +":"+ method.getName());
                children.setParentId(parent.getId());
                String childUrl = getChildUrl(method);
                children.setUrl(parent.getUrl()+childUrl);//访问路径

                //检查db里面是否存在当前权限
                Permission permissionChild = permissionService.queryBySn(children.getSn());
                if(permissionChild == null){
                    permissionService.save(children);
                }else{
                    parent.setId(permissionChild.getId());
                    permissionService.update(children);
                }

            }
        }
    }

    /**
     * 方法上可能存在很多不同的注解
     * @param method
     * @return
     */
    private String getChildUrl(Method method){

        RequestMapping annotation = method.getAnnotation(RequestMapping.class);
        if (annotation!=null){
            return annotation.value().length>0?annotation.value()[0]:"";
        }

        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping!=null){
            return getMapping.value().length>0?getMapping.value()[0]:"";
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping!=null){
            return putMapping.value().length>0?putMapping.value()[0]:"";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping!=null){
            return deleteMapping.value().length>0?deleteMapping.value()[0]:"";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping!=null){
            return postMapping.value().length>0?postMapping.value()[0]:"";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping!=null){
            return patchMapping.value().length>0?patchMapping.value()[0]:"";
        }
        return "";
    }
}
